import java.util.HashSet;
import java.io.*;
import java.sql.*;

/**
 * Created by IntelliJ IDEA.
 * User: christopher_moore
 * Date: Jul 24, 2007
 * Time: 2:38:36 PM
 * To change this template use File | Settings | File Templates.
 */
public class AuctionExtract {
    static final String AUCTIONEER_FILENAME = "Auctioneer.lua";
    static final String BEANCOUNTER_FILENAME = "BeanCounter.lua";
    private static Connection theDb;
    static final String DB_URL = "jdbc:postgresql://www.moores-r.us/auctions";
    static final String DB_USER = "apache";
    static final String DB_PASSWD = "apache";
    static public final boolean DEBUG = true;
    static private HashSet<String> itemKeys;
    static private HashSet<String> auctionKeys;
    static private int newAuctions = 0;
    static private int newItems = 0;

    public static void main(String[] args) {

        // Open the  database
        try {
            Class.forName("org.postgresql.Driver");
        } catch (ClassNotFoundException e) {
            System.out.println("Unable to load Postgres driver.");
            return;
        }

        if (DEBUG) {
            System.out.println("Postgres driver loaded");
        }

        try {
            theDb = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWD);
        } catch (SQLException e) {
            System.out.println("Unable to connect to database");
            return;
        }

        if (DEBUG) {
            System.out.println("Connected to database");
            System.out.println("Reading item keys");
        }

        // Read current item keys
        try {
            itemKeys = new HashSet<String>();
            String sqlText = "select object_id from items";
            Statement sql = theDb.createStatement();
            ResultSet keys = sql.executeQuery(sqlText);
            while (keys.next()) {
                itemKeys.add(keys.getString("object_id"));
            }
        } catch (SQLException e) {
            System.out.println("Failed to get set of item keys from database");
            return;
        }

        if (DEBUG) {
            System.out.println("Reading auction keys");
        }

        // Read current auction keys
        try {
            auctionKeys = new HashSet<String>();
            String sqlText = "select server_faction, auction_id from auctions";
            Statement sql = theDb.createStatement();
            ResultSet keys = sql.executeQuery(sqlText);
            while (keys.next()) {
                itemKeys.add(keys.getString("server_faction") + ":" + keys.getString("auction_id"));
            }
        } catch (SQLException e) {
            System.out.println("Failed to get set of auction keys from database");
            return;
        }


        if (DEBUG) {
            System.out.println("Done reading keys");
        }

        // Open the file
        BufferedReader in;
        try {
            in = new BufferedReader(new FileReader(AUCTIONEER_FILENAME));
        } catch (FileNotFoundException e) {
            System.out.println("Can't find file " + AUCTIONEER_FILENAME);
            return;
        }

        if (DEBUG) {
            System.out.println("Processing items");
        }

        // Read items from the file
        readItems(in);

        if (DEBUG) {
            System.out.println("Added " + newItems + " new items");
        }

        // Read snapshots from the file
        // Close and reopen the file first. (Why doesn't Java have rewind()?)
        try {
            in.close();
            in = new BufferedReader(new FileReader(AUCTIONEER_FILENAME));
        } catch (FileNotFoundException e) {
            System.out.println("Can't find file " + AUCTIONEER_FILENAME);
            return;
        } catch (IOException e) {
            System.out.println("Can't close and reopen file " + AUCTIONEER_FILENAME);
            return;
        }

        if (DEBUG) {
            System.out.println("Processing auctions");
        }

        readSnapshots(in);

        if (DEBUG) {
            System.out.println("Added " + newAuctions + " new auctions");
        }

        try {
            theDb.close();
        } catch (SQLException e) {
            System.out.println("Can't close the database connection");
        }


    }


    /**
     *
     * @param in
     *
     * Process:
     *  - Read lines until we find "AuctioneerItemDB"
     *  - Read lines until we find " [\"items\"]"
     *  - Read and process lines, passing them to the Item constructor, until we find "},"
     *
     */
    private static void readItems(BufferedReader in) {
        String line;
        int state = 0;

        try {
            while ((line = in.readLine()) != null) {
                String trimmedLine = line.trim();
                switch (state) {
                    case 0: // Looking for "AuctioneerItemDB"
                        if (trimmedLine.contains("AuctioneerItemDB")) {
                            state = 1;
                        }
                        break;
                    case 1: // Looking for "[\"items\"]"
                        if (trimmedLine.contains("[\"items\"]")) {
                            state = 2;
                        }
                        break;
                    case 2: // Processing lines, looking for end marker
                        if (trimmedLine.equals("},")) {
                            // Done
                            return;
                        } else {
                            Item newItem = new Item(trimmedLine);

                            if (! itemKeys.contains(newItem.getItemKey())) {
                                // Write the item to the database
                                newItem.write(theDb);
                                ++newItems;
                            }

                        }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void readSnapshots(BufferedReader in) {
        String line;
        String serverFaction;

        try {
            // Look for AuctioneerSnapshotDB

            while ((line = in.readLine()) != null) {
                String trimmedLine = line.trim();
                if (trimmedLine.contains("AuctioneerSnapshotDB")) {
                    break;
                }
            }

            boolean done = false;
            while (!done) {
                line = in.readLine();
                if (line == null) {
                    done = true;
                } else {
                    serverFaction = getLeftHandSide(line);
                    if (serverFaction == null) {
                        // Done;
                        done = true;
                    } else {
                        // Process the whole section
                        readOneSnapshot(in, serverFaction);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * When this method is called we've already read the header line for the
     * server-faction snapshot:
     *
     * 	["muradin-horde"] = {              <=== We've already read this line
           ["nextAuctionId"] = 250214,
           ["version"] = 3,
           ["auctionIdsByItemKey"] = {
                ["21764:0:0"] = "246490;246491;246492;246493",
                    .
                    .
                    .
           },
           ["auctions"] = {
                [249306] = "8116;0;0;893573722;1;15680;19600;Underbridge;0;0;3;1185043466;1185072266",
                [249818] = "4306;0;0;417810768;20;4500;9000;Vilenth;0;0;4;1185043384;1185129784",
                     .
                     .
                     .
           },
           ["ahKey"] = "muradin-horde",
           ["updates"] = {
             "1185043531;;0;0;0;0;0;0", -- [1]
           },
         },   <===    server-faction end marker
     *
     *
     *  We need to:
     *    - read a line
     *    - get the section name out of it
     *    - process the section, which may include reading everything up to a closing },
     *    - repeat
     *
     *  We're done when we read a line and get the section name and get a null, indicating there
     *  is no section name.  This should be the end marker for the server-faction section.
     *
     * @param in
     * @param serverFactionName
     */

    private static void readOneSnapshot(BufferedReader in, String serverFactionName) {
        String sectionName;
        String line;
        String itemKey;

        boolean done=false;
        try {
            while (!done) {

                // Read a line
                line = in.readLine();

                // Get the section name from the line
                sectionName = getLeftHandSide(line);

                if (sectionName == null) {
                    // We're done
                    done = true;
                } else if (sectionName.equals("nextAuctionId")) {
                    // Nothing special to do here
                } else if (sectionName.equals("version")) {
                    // Nothing special to do here
                } else if (sectionName.equals("auctionIdsByItemKey")) {
                    boolean sectionDone = false;
                    while (!sectionDone) {
                        line = in.readLine();
                        itemKey = getLeftHandSide(line);
                        if (itemKey == null) {
                            // Done with this subsection
                            sectionDone = true;
                        } else {
                            // Do nothing
                        }
                    }
                } else if (sectionName.equals("auctions")) {
                    boolean sectionDone = false;
                    while (!sectionDone) {
                        line = in.readLine();
                        itemKey = getLeftHandSideNoQuotes(line);
                        if (itemKey == null) {
                            // Done with this subsection
                            sectionDone = true;
                        } else {
                            Auction newAuction = new Auction(line.trim());
                            if (newAuction.getAuctionId() != -1) {
                                newAuction.setServerFaction(serverFactionName);
                                String key = newAuction.getKey();
                                if (! auctionKeys.contains(key)) {
                                    newAuction.write(theDb);
                                    ++newAuctions;
                                }
                            }
                        }
                    }
                } else if (sectionName.equals("ahKey")) {
                    // Nothing special to do here
                } else if (sectionName.equals("updates")) {
                    // Ignore this section, but it has multiple lines so we have to consume it
                    boolean sectionDone = false;
                    while (!sectionDone) {
                        line = in.readLine();
                        if (line.contains("},")) {
                            sectionDone = true;
                        }
                    }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();

        }




    }






    /**
     * Given a line read from the file, look for something
     * of the form ["<text>"] = <value>
     * and return the "text" part
     * If we don't find [" and "] return null
     *
     * @param line
     * @return String name of section found
     */

    private static String getLeftHandSide(String line) {
        String sectionName;
        int delim1;
        int delim2;

        delim1 = line.indexOf("[\"");
        delim2 = line.indexOf("\"]");

        if ((delim1 == -1) || (delim2 == -1)) {
            return null;
        }

        sectionName = line.substring(delim1+2, delim2);

        return sectionName;


    }

    private static String getLeftHandSideNoQuotes(String line) {
        String sectionName;
        int delim1;
        int delim2;

        delim1 = line.indexOf("[");
        delim2 = line.indexOf("]");

        if ((delim1 == -1) || (delim2 == -1)) {
            return null;
        }

        sectionName = line.substring(delim1+1, delim2);

        return sectionName;


    }


}
